package main

import (
	"context"
	"errors"
	"fmt"
	"time"

	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/mongo"
	"go.mongodb.org/mongo-driver/mongo/options"
)

type ShipVoyageRepo interface {
	GetByShipID(shipID ShipIDType) (*ShipVoyage, error)
	Update(sv ShipVoyage) error
}

type ShipVoyageRepoStruct struct {
	config      ShipVoyageRepoConfig
	mongoClient *mongo.Client
	collection  *mongo.Collection
}

type ShipVoyageRepoConfig struct {
	MongoURI   string        `json:"mongoUri,omitempty"`
	DBName     string        `json:"dbName,omitempty"`
	Collection string        `json:"collection,omitempty"`
	Timeout    time.Duration `json:"timeout,omitempty"`
}

func NewShipVoyageRepo(config ShipVoyageRepoConfig) (*ShipVoyageRepoStruct, error) {
	uri := config.MongoURI
	opts := options.Client().ApplyURI(uri)
	opts = opts.SetDirect(true)
	client, err := mongo.NewClient(opts)
	if err != nil {
		return nil, err
	}
	ctx, _ := context.WithTimeout(context.Background(), config.Timeout)
	if err != nil {
		return nil, err
	}
	err = client.Connect(ctx)
	if err != nil {
		return nil, err
	}
	db := client.Database(config.DBName)
	coll := db.Collection(config.Collection)
	return &ShipVoyageRepoStruct{
		config:      config,
		mongoClient: client,
		collection:  coll,
	}, nil
}

func (r *ShipVoyageRepoStruct) GetByShipID(shipID ShipIDType) (*ShipVoyage, error) {
	ctx, cancel := context.WithTimeout(context.Background(), r.config.Timeout)
	defer cancel()
	filter := bson.M{"shipID": shipID, "active": true}
	res := r.collection.FindOne(ctx, filter)
	err := res.Err()
	if err != nil {
		return nil, err
	}
	var sv ShipVoyage
	err = res.Decode(&sv)
	// raw, err := res.DecodeBytes()

	fmt.Printf("err: %v\n", err)
	fmt.Printf("sv: %+v\n", sv)
	return &ShipVoyage{}, err
}

func (r *ShipVoyageRepoStruct) Update(sv ShipVoyage) error {
	return errors.New("unimplementd")
}
